home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / jvm.e < prev    next >
Text File  |  2000-03-25  |  27KB  |  939 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class JVM
  17.    --
  18.    -- Handling of Java Virtual Machine byte code generation.
  19.    --
  20.  
  21. inherit CODE_PRINTER;
  22.  
  23. creation make
  24.  
  25. feature {NONE}
  26.  
  27.    make is
  28.       do
  29.       end;
  30.  
  31. feature
  32.  
  33.    current_frame: RUN_FEATURE;
  34.          -- Current method or current field.
  35.  
  36.    argument_offset_of(an: ARGUMENT_NAME): INTEGER is
  37.       require
  38.          an /= Void
  39.       do
  40.          Result := current_frame.jvm_argument_offset(an);
  41.       ensure
  42.          Result >= 0
  43.       end;
  44.  
  45.    local_offset_of(ln: LOCAL_NAME): INTEGER is
  46.       require
  47.          ln /= Void
  48.       do
  49.          Result := current_frame.jvm_local_variable_offset(ln);
  50.       ensure
  51.          Result >= 0
  52.       end;
  53.  
  54.    std_is_equal(rc: RUN_CLASS; wa: ARRAY[RUN_FEATURE_2]) is
  55.          -- Produce byte code to compare two operands at top of stack.
  56.          -- Result `1'  (true) or `0' (false) is left at top of stack.
  57.       require
  58.          not rc.current_type.is_basic_eiffel_expanded
  59.       local
  60.          ca: like code_attribute;
  61.          rf2: RUN_FEATURE_2;
  62.          point1, point2, space, i: INTEGER;
  63.       do
  64.          ca := code_attribute;
  65.          if wa = Void then
  66.             if rc.current_type.is_expanded then
  67.                ca.opcode_pop2;
  68.                ca.opcode_iconst_1;
  69.             else
  70.                ca.opcode_swap;
  71.                ca.opcode_pop;
  72.                rc.opcode_instanceof;
  73.             end;
  74.          else
  75.             ca.branches.clear; -- pop2 then false
  76.             if rc.current_type.is_reference then
  77.                ca.opcode_dup;
  78.                rc.opcode_instanceof;
  79.                ca.branches.add_last(ca.opcode_ifeq);
  80.             end;
  81.             from
  82.                i := wa.upper;
  83.             until
  84.                i = 0
  85.             loop
  86.                rf2 := wa.item(i);
  87.                space := rf2.result_type.jvm_stack_space - 1;
  88.                if i > 1 then
  89.                   ca.opcode_dup2;
  90.                end;
  91.                space := rc.opcode_getfield(rf2);
  92.                if space = 0 then
  93.                   ca.opcode_swap;
  94.                else
  95.                   ca.opcode_dup2_x1;
  96.                   ca.opcode_pop2;
  97.                end;
  98.                space := rc.opcode_getfield(rf2);
  99.                if i > 1 then
  100.                   ca.branches.add_last(rf2.result_type.jvm_if_x_ne);
  101.                else
  102.                   point1 := rf2.result_type.jvm_if_x_ne;
  103.                end;
  104.                i := i - 1;
  105.             end;
  106.             ca.opcode_iconst_1;
  107.             point2 := ca.opcode_goto;
  108.             ca.resolve_branches;
  109.             ca.opcode_pop2;
  110.             ca.resolve_u2_branch(point1);
  111.             ca.opcode_iconst_0;
  112.             ca.resolve_u2_branch(point2);
  113.          end;
  114.       end;
  115.  
  116.    fields_by_fields_copy(wa: ARRAY[RUN_FEATURE_2]) is
  117.          -- Stack : ..., destination, model => ..., destination
  118.          -- Assume the checkcast is already done.
  119.       local
  120.          ca: like code_attribute;
  121.          rf2: RUN_FEATURE_2;
  122.          idx, space, i: INTEGER;
  123.       do
  124.          ca := code_attribute;
  125.          if wa /= Void then
  126.             from
  127.                i := wa.upper;
  128.             until
  129.                i = 0
  130.             loop
  131.                ca.opcode_dup2;
  132.                rf2 := wa.item(i);
  133.                idx := constant_pool.idx_fieldref(rf2);
  134.                space := rf2.result_type.jvm_stack_space;
  135.                ca.opcode_getfield(idx,space - 1);
  136.                ca.opcode_putfield(idx,-(space + 1));
  137.                i := i - 1;
  138.             end;
  139.          end;
  140.          ca.opcode_pop;
  141.       end;
  142.  
  143. feature {RUN_FEATURE}
  144.  
  145.    add_field(rf: RUN_FEATURE) is
  146.       require
  147.          rf /= Void
  148.       do
  149.          check
  150.             not fields.fast_has(rf)
  151.          end;
  152.          fields.add_last(rf);
  153.       ensure
  154.          fields.fast_has(rf)
  155.       end;
  156.  
  157. feature {SMALL_EIFFEL}
  158.  
  159.    prepare_output_directory is
  160.          -- A new output directory is created or the content of the old 
  161.          -- existing one is cleared.
  162.       require
  163.          small_eiffel.is_ready
  164.       local
  165.          output_name: STRING;
  166.          basic_directory: BASIC_DIRECTORY;
  167.       do
  168.          output_name := run_control.output_name;
  169.          if output_name = Void then
  170.             output_name := run_control.root_class.twin;
  171.             output_name.to_lower;
  172.          elseif output_name.has_suffix(class_suffix) then
  173.             output_name.remove_suffix(class_suffix);
  174.          end;
  175.          echo.put_string("Trying to prepare directory %"");
  176.          echo.put_string(output_name);
  177.          echo.put_string("%" to store Java byte code.%N");
  178.          basic_directory.connect_to(output_name);
  179.          if basic_directory.is_connected then
  180.             basic_directory.disconnect;
  181.             basic_directory.remove_files_of(output_name);
  182.         -- *******
  183.             -- Because a bug of BASIC_DIRECTORY.remove_files_of under
  184.         -- WINDOWS, we may need to recreate the directory itself :
  185.             basic_directory.connect_to(output_name);
  186.             if not basic_directory.is_connected then
  187.                if basic_directory.create_new_directory(output_name) then
  188.                end
  189.             end
  190.         -- *******
  191.          elseif basic_directory.create_new_directory(output_name) then
  192.          end;
  193.       ensure
  194.          run_control.output_name /= Void
  195.       end;
  196.  
  197.    write_jvm_root_class is
  198.       local
  199.          idx: INTEGER;
  200.          cp: like constant_pool;
  201.          ca: like code_attribute;
  202.          output_name: STRING;
  203.       do
  204.          cp := constant_pool;
  205.          ca := code_attribute
  206.          output_name := run_control.output_name;
  207.          system_tools.class_file_path(out_file_path,output_name,fz_jvm_root);
  208.          bfw_connect(out_file,out_file_path);
  209.          start_basic;
  210.          this_class_idx := cp.idx_class2(jvm_root_class);
  211.          super_class_idx := cp.idx_java_lang_object;
  212.          -- Fields :
  213.          args_field;
  214.          manifest_string_pool.jvm_define_fields;
  215.          once_routine_pool.jvm_define_fields;
  216.          if run_control.no_check then
  217.             field_info.add(9,cp.idx_utf8(fz_58),cp.idx_utf8(fz_41));
  218.          end;
  219.          -- Methods :
  220.          method_info.add_init(fz_java_lang_object);
  221.          -- The _initialize_eiffel_runtime static method :
  222.          current_frame := Void;
  223.          method_info.start(9,fz_28,fz_23);
  224.          -- Set `args' field to store command line arguments.
  225.          ca.opcode_aload_0;
  226.          ca.opcode_putstatic(args_field_idx,-1);
  227.          manifest_string_pool.jvm_initialize_fields;
  228.          once_routine_pool.jvm_initialize_fields;
  229.          if run_control.no_check then
  230.             idx := cp.idx_fieldref3(jvm_root_class,fz_58,fz_41);
  231.             ca.opcode_iconst_0;
  232.             ca.opcode_putstatic(idx,-1);
  233.          end;
  234.          ca.opcode_return;
  235.          method_info.finish;
  236.          --    For switches :
  237.          switch_collection.jvm_define;
  238.          finish_class;
  239.       end;
  240.  
  241.    write_main_class(rf3: RUN_FEATURE_3) is
  242.          -- Write Java Byte Code for main class to call `rf3'.
  243.       require
  244.          rf3 /= Void;
  245.          small_eiffel.is_ready
  246.       local
  247.          idx: INTEGER;
  248.          cp: like constant_pool;
  249.          ca: like code_attribute;
  250.       do
  251.          cp := constant_pool;
  252.          ca := code_attribute;
  253.          out_file_path.copy(run_control.output_name);
  254.          out_file_path.append(class_suffix);
  255.          bfw_connect(out_file,out_file_path);
  256.          start_basic;
  257.          this_class_idx := cp.idx_class2(run_control.output_name);
  258.          super_class_idx := cp.idx_java_lang_object;
  259.          -- Methods :
  260.          --    The main method :
  261.          current_frame := Void;
  262.          method_info.add_init(fz_java_lang_object);
  263.          method_info.start(9,fz_main,fz_23);
  264.          ca.opcode_aload_0;
  265.          idx := cp.idx_methodref3(jvm_root_class,fz_28,fz_23);
  266.          ca.opcode_invokestatic(idx,0);
  267.          rf3.run_class.jvm_basic_new;
  268.          idx := cp.idx_methodref(rf3);
  269.          ca.opcode_invokevirtual(idx,-1);
  270.          ca.opcode_return;
  271.          method_info.finish;
  272.          finish_class;
  273.       end;
  274.  
  275. feature {CODE_ATTRIBUTE}
  276.  
  277.    max_locals: INTEGER is
  278.       do
  279.          if current_frame /= Void then
  280.             Result := current_frame.jvm_max_locals;
  281.          else
  282.             Result := 4;
  283.          end;
  284.       end;
  285.  
  286. feature {RUN_CLASS,SWITCH_COLLECTION}
  287.  
  288.    set_current_frame(cf: like current_frame) is
  289.       do
  290.          current_frame := cf;
  291.       end;
  292.  
  293. feature {CP_INFO}
  294.  
  295.    b_put_u1(byte: CHARACTER) is
  296.       require
  297.          byte.code <= 255
  298.       do
  299.          out_file.put_byte(byte);
  300.       end;
  301.  
  302. feature {CONSTANT_POOL,FIELD_INFO,METHOD_INFO}
  303.  
  304.    b_put_u2(u2: INTEGER) is
  305.       do
  306.          b_put_u1((u2 // 256).to_character);
  307.          b_put_u1((u2 \\ 256).to_character);
  308.       end;
  309.  
  310. feature {CP_INFO,FIELD_INFO,METHOD_INFO}
  311.  
  312.    b_put_byte_string(str: STRING) is
  313.       require
  314.          str /= Void
  315.       local
  316.          i: INTEGER;
  317.       do
  318.          from
  319.             i := 1;
  320.          until
  321.             i > str.count
  322.          loop
  323.             b_put_u1(str.item(i));
  324.             i := i + 1;
  325.          end;
  326.       end;
  327.  
  328. feature {NATIVE_SMALL_EIFFEL}
  329.  
  330.    push_se_argc is
  331.       local
  332.          ca: like code_attribute;
  333.       do
  334.          ca := code_attribute;
  335.          ca.opcode_getstatic(args_field_idx,1);
  336.          ca.opcode_arraylength;
  337.          ca.opcode_iconst_1;
  338.          ca.opcode_iadd;
  339.       end;
  340.  
  341.    push_se_argv is
  342.       local
  343.          point1, point2, i: INTEGER;
  344.          ca: like code_attribute;
  345.       do
  346.          ca := code_attribute;
  347.          ca.opcode_getstatic(args_field_idx,1);
  348.          i := push_ith_argument(1)
  349.          ca.opcode_dup;
  350.          point1 := ca.opcode_ifeq;
  351.          ca.opcode_iconst_1;
  352.          ca.opcode_isub;
  353.          ca.opcode_aaload;
  354.          point2 := ca.opcode_goto;
  355.          ca.resolve_u2_branch(point1);
  356.          ca.opcode_pop2;
  357.          i := constant_pool.idx_string(run_control.output_name);
  358.          ca.opcode_ldc(i);
  359.          ca.resolve_u2_branch(point2);
  360.          ca.opcode_java_string2eiffel_string;
  361.       end;
  362.  
  363. feature {CALL_PROC_CALL}
  364.  
  365.    call_proc_call_mapping(cpc: CALL_PROC_CALL) is
  366.       local
  367.          target: EXPRESSION;
  368.          target_type: TYPE;
  369.          rc: RUN_CLASS;
  370.          running: ARRAY[RUN_CLASS];
  371.          switch: SWITCH;
  372.          rf: RUN_FEATURE;
  373.          result_type: TYPE;
  374.       do
  375.          target := cpc.target;
  376.          target_type := target.result_type.run_type;
  377.          rf := cpc.run_feature;
  378.          if target.is_current then
  379.             push_direct(cpc);
  380.             rf.mapping_jvm;
  381.             pop
  382.          elseif target.is_manifest_string then
  383.             push_direct(cpc);
  384.             rf.mapping_jvm;
  385.             pop
  386.          elseif target_type.is_expanded then
  387.             push_direct(cpc);
  388.             rf.mapping_jvm;
  389.             pop
  390.          else
  391.             running := target_type.run_class.running;
  392.             check
  393.                running /= Void
  394.             end;
  395.             if running.count = 1 then
  396.                push_check(cpc);
  397.                rf := running.first.dynamic(rf);
  398.                rf.mapping_jvm;
  399.                pop
  400.             else
  401.                switch_count := switch_count + 1;
  402.                switch.jvm_mapping(cpc);
  403.             end;
  404.          end;
  405.          result_type := rf.result_type;
  406.          -- Optional checkcast for result :
  407.          if result_type /= Void then
  408.             if not result_type.is_none then
  409.                rc := result_type.run_class;
  410.                if rc /= Void then
  411.                   running := rc.running;
  412.                   if running /= Void and then running.count = 1 then
  413.                      running.first.opcode_checkcast;
  414.                   end;
  415.                end;
  416.             end;
  417.          end;
  418.       end;
  419.  
  420. feature {RUN_CLASS}
  421.  
  422.    prepare_fields is
  423.       local
  424.          i: INTEGER;
  425.          rf: RUN_FEATURE;
  426.       do
  427.          from
  428.             i := fields.upper;
  429.          until
  430.             i < 0
  431.          loop
  432.             rf := fields.item(i);
  433.             rf.jvm_define;
  434.             i := i - 1;
  435.          end;
  436.       end;
  437.  
  438.    prepare_methods is
  439.       local
  440.          i: INTEGER;
  441.       do
  442.          from
  443.             i := methods.upper;
  444.          until
  445.             i < 0
  446.          loop
  447.             set_current_frame(methods.item(i));
  448.             current_frame.jvm_define;
  449.             i := i - 1;
  450.          end;
  451.       end;
  452.  
  453.    start_new_class(rc: RUN_CLASS) is
  454.       require
  455.          run_control.output_name /= Void
  456.       local
  457.          name_idx, type_idx: INTEGER;
  458.          cp: like constant_pool;
  459.          output_name: STRING;
  460.       do
  461.          cp := constant_pool;
  462.          start_basic;
  463.          tmp_string.copy(rc.unqualified_name);
  464.          output_name := run_control.output_name;
  465.          system_tools.class_file_path(out_file_path,output_name,tmp_string);
  466.          bfw_connect(out_file,out_file_path);
  467.          this_class_idx := rc.jvm_constant_pool_index;
  468.          super_class_idx := cp.idx_jvm_root_class;
  469.          method_info.add_init(jvm_root_class);
  470.          -- <clinit> :
  471.          method_info.start(9,fz_76,fz_29);
  472.          if run_control.generating_type_used then
  473.             name_idx := cp.idx_utf8(as_generating_type);
  474.             type_idx := cp.idx_eiffel_string_descriptor;
  475.             field_info.add(9,name_idx,type_idx);
  476.             name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  477.             code_attribute.opcode_aconst_null;
  478.             code_attribute.opcode_putstatic(name_idx,-1);
  479.          end;
  480.          if run_control.generating_type_used then
  481.             name_idx := cp.idx_utf8(as_generator);
  482.             field_info.add(9,name_idx,type_idx);
  483.             name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  484.             code_attribute.opcode_aconst_null;
  485.             code_attribute.opcode_putstatic(name_idx,-1);
  486.          end;
  487.          code_attribute.opcode_return;
  488.          method_info.finish;
  489.          rc.jvm_define_class_invariant;
  490.       end;
  491.  
  492.    finish_class is
  493.          -- Really print the class file.
  494.       do
  495.          put_magic;
  496.          put_minor_version;
  497.          put_major_version;
  498.          constant_pool.write_bytes;
  499.          b_put_u2(access_flags);
  500.          b_put_u2(this_class_idx);
  501.          b_put_u2(super_class_idx);
  502.          -- interfaces_count :
  503.          b_put_u2(0);
  504.          field_info.write_bytes;
  505.          method_info.write_bytes;
  506.          -- attributes_count :
  507.          b_put_u2(0);
  508.          out_file.disconnect;
  509.       end;
  510.  
  511.    push_expanded_initialize(rf: RUN_FEATURE) is
  512.       do
  513.          stack_push(C_expanded_initialize);
  514.          stack_rf.put(rf,top);
  515.       end;
  516.  
  517.    define_class_invariant_method(ci: CLASS_INVARIANT) is
  518.       require
  519.          run_control.invariant_check;
  520.          ci /= Void
  521.       local
  522.          ca: like code_attribute;
  523.          cp: like constant_pool;
  524.       do
  525.          ca := code_attribute;
  526.          cp := constant_pool;
  527.          method_info.start(1,fz_invariant,fz_29);
  528.          stack_push(C_switch);
  529.          ci.compile_to_jvm(true);
  530.          pop;
  531.          ca.opcode_return;
  532.          method_info.finish;
  533.       end;
  534.  
  535. feature {NATIVE}
  536.  
  537.    inside_twin(cpy: RUN_FEATURE) is
  538.       do
  539.          stack_push(C_inside_twin);
  540.          stack_rf.put(cpy,top);
  541.          cpy.mapping_jvm;
  542.          pop;
  543.       end;
  544.  
  545. feature {CREATION_CALL}
  546.  
  547.    inside_new(rf: RUN_FEATURE; cpc: CALL_PROC_CALL) is
  548.       require
  549.          rf /= Void;
  550.          cpc /= Void
  551.       do
  552.          stack_push(C_inside_new);
  553.          stack_rf.put(rf,top);
  554.          stack_cpc.put(cpc,top);
  555.          rf.mapping_jvm;
  556.          pop;
  557.       end;
  558.  
  559. feature {RUN_FEATURE,NATIVE}
  560.  
  561.    add_method(rf: RUN_FEATURE) is
  562.       require
  563.          rf /= Void
  564.       do
  565.          check
  566.             not methods.fast_has(rf)
  567.          end;
  568.          methods.add_last(rf);
  569.       ensure
  570.          methods.fast_has(rf)
  571.       end;
  572.  
  573.    target_position: POSITION is
  574.       local
  575.          code: INTEGER;
  576.       do
  577.          code := stack_code.item(top);
  578.          inspect
  579.             code
  580.          when C_direct_call, C_check_id then
  581.             Result := stack_cpc.item(top).start_position;
  582.          when C_inside_twin then
  583.          when C_switch then
  584.          when C_expanded_initialize then
  585.          when C_inside_new then
  586.             Result := stack_cpc.item(top).start_position;
  587.          else
  588.          end;
  589.       end;
  590.  
  591.    push_target is
  592.          -- Produce java byte code in order to push target on the
  593.          -- jvm stack.
  594.       local
  595.          code: INTEGER;
  596.       do
  597.          code := stack_code.item(top);
  598.          inspect
  599.             code
  600.          when C_direct_call then
  601.             stack_cpc.item(top).target.compile_to_jvm;
  602.          when C_check_id then
  603.             opcode_check_id_for(stack_cpc.item(top).target);
  604.          when C_switch then
  605.             code_attribute.opcode_aload_0;
  606.          when C_expanded_initialize then
  607.             code_attribute.opcode_dup;
  608.          when C_inside_new then
  609.             code_attribute.opcode_dup;
  610.          when C_inside_twin then
  611.             code_attribute.opcode_aload_1;
  612.          end;
  613.       end;
  614.  
  615.    push_target_as_target is
  616.          -- Same as `push_target' but with class invariant check
  617.          -- and the checkcast opcode.
  618.       local
  619.          target: EXPRESSION;
  620.          rc: RUN_CLASS;
  621.          code: INTEGER;
  622.       do
  623.          code := stack_code.item(top);
  624.          inspect
  625.             code
  626.          when C_direct_call then
  627.             target := stack_cpc.item(top).target;
  628.             target.compile_target_to_jvm;
  629.          when C_check_id then
  630.             target := stack_cpc.item(top).target;
  631.             opcode_check_id_for(target);
  632.          when C_switch then
  633.             code_attribute.opcode_aload_0;
  634.             rc := stack_rf.item(top).current_type.run_class;
  635.             rc.opcode_checkcast;
  636.          when C_expanded_initialize then
  637.             code_attribute.opcode_dup;
  638.          when C_inside_new then
  639.             code_attribute.opcode_dup;
  640.          when C_inside_twin then
  641.             code_attribute.opcode_aload_1;
  642.          when C_precursor then
  643.             stack_rf.item(top).current_type.jvm_push_local(0);
  644.          end;
  645.       end;
  646.  
  647.    drop_target is
  648.       local
  649.          code: INTEGER;
  650.          cpc: CALL_PROC_CALL;
  651.          e: EXPRESSION;
  652.       do
  653.          code := stack_code.item(top);
  654.          inspect
  655.             code
  656.          when C_direct_call, C_check_id then
  657.             cpc := stack_cpc.item(top);
  658.             e ?= cpc;
  659.             if e = Void or else not e.can_be_dropped then
  660.                cpc.target.compile_to_jvm;
  661.                if cpc.run_feature.current_type.jvm_stack_space = 1 then
  662.                   code_attribute.opcode_pop;
  663.                else
  664.                   code_attribute.opcode_pop2;
  665.                end;
  666.             end;
  667.          when C_switch then
  668.          when C_expanded_initialize then
  669.          when C_inside_new then
  670.          when C_inside_twin then
  671.          end;
  672.       end;
  673.  
  674.    drop_ith_argument(i: INTEGER) is
  675.       local
  676.          space: INTEGER;
  677.       do
  678.          from
  679.             space := push_ith_argument(i);
  680.          until
  681.             space = 0
  682.          loop
  683.             code_attribute.opcode_pop;
  684.             space := space - 1;
  685.          end;
  686.       end;
  687.  
  688.    push_arguments: INTEGER is
  689.       local
  690.          code: INTEGER;
  691.          cpc: CALL_PROC_CALL;
  692.          eal: EFFECTIVE_ARG_LIST;
  693.          rf, dyn_rf: RUN_FEATURE;
  694.          fal: FORMAL_ARG_LIST;
  695.       do
  696.          code := stack_code.item(top);
  697.          inspect
  698.             code
  699.          when C_direct_call, C_check_id then
  700.             cpc := stack_cpc.item(top);
  701.             eal := cpc.arguments;
  702.             if eal /= Void then
  703.                rf := cpc.run_feature;
  704.                fal := rf.arguments;
  705.                Result := eal.compile_to_jvm(fal);
  706.             end;
  707.          when C_switch then
  708.             rf := stack_static_rf.item(top);
  709.             dyn_rf := stack_rf.item(top);
  710.             fal := rf.arguments;
  711.             if fal /= Void then
  712.                Result := fal.jvm_switch_push(dyn_rf.arguments);
  713.             end;
  714.          when C_expanded_initialize then
  715.             check
  716.                stack_rf.item(top).arguments = Void
  717.             end;
  718.          when C_inside_new then
  719.             cpc := stack_cpc.item(top);
  720.             eal := cpc.arguments;
  721.             if eal /= Void then
  722.                rf := stack_rf.item(top);
  723.                fal := rf.arguments;
  724.                Result := eal.compile_to_jvm(fal);
  725.             end;
  726.          when C_inside_twin then
  727.             Result := push_ith_argument(1);
  728.          when C_precursor then
  729.             eal := stack_args.item(top);
  730.             if eal /= Void then
  731.                rf := stack_rf.item(top);
  732.                fal := rf.arguments;
  733.                Result := eal.compile_to_jvm(fal);
  734.             end;
  735.          end;
  736.       end;
  737.  
  738.    push_ith_argument(i: INTEGER): INTEGER is
  739.       local
  740.          code: INTEGER;
  741.          cpc: CALL_PROC_CALL;
  742.          eal: EFFECTIVE_ARG_LIST;
  743.          rf, dyn_rf: RUN_FEATURE;
  744.          fal: FORMAL_ARG_LIST;
  745.       do
  746.          code := stack_code.item(top);
  747.          inspect
  748.             code
  749.          when C_direct_call, C_check_id then
  750.             cpc := stack_cpc.item(top);
  751.             eal := cpc.arguments;
  752.             rf := cpc.run_feature;
  753.             fal := rf.arguments;
  754.             Result := eal.compile_to_jvm_ith(fal,i);
  755.          when C_switch then
  756.             rf := stack_static_rf.item(top);
  757.             dyn_rf := stack_rf.item(top);
  758.             fal := rf.arguments;
  759.             Result := fal.jvm_switch_push_ith(dyn_rf.arguments,i);
  760.          when C_expanded_initialize then
  761.             check
  762.                false
  763.             end;
  764.          when C_inside_new then
  765.             cpc := stack_cpc.item(top);
  766.             eal := cpc.arguments;
  767.             rf := stack_rf.item(top);
  768.             fal := rf.arguments;
  769.             Result := eal.compile_to_jvm_ith(fal,i);
  770.          when C_inside_twin then
  771.             code_attribute.opcode_aload_0;
  772.             Result := 1;
  773.          end;
  774.       end;
  775.  
  776. feature {SWITCH}
  777.  
  778.    push_switch(rf, static_rf: RUN_FEATURE) is
  779.       require
  780.          rf /= Void;
  781.          static_rf /= Void;
  782.          rf.run_class.dynamic(static_rf) = rf
  783.       do
  784.          stack_push(C_switch);
  785.          stack_rf.put(rf,top);
  786.          stack_static_rf.put(static_rf,top);
  787.       end;
  788.  
  789. feature {NONE}
  790.  
  791.    fields: FIXED_ARRAY[RUN_FEATURE] is
  792.       once
  793.          !!Result.with_capacity(4);
  794.       end;
  795.  
  796.    methods: FIXED_ARRAY[RUN_FEATURE] is
  797.       once
  798.          !!Result.with_capacity(64);
  799.       end;
  800.  
  801.    access_flags: INTEGER is 33;
  802.          -- To allow any external access.
  803.  
  804.    this_class_idx: INTEGER;
  805.  
  806.    super_class_idx: INTEGER;
  807.  
  808.    start_basic is
  809.       do
  810.          fields.clear;
  811.          methods.clear;
  812.          constant_pool.clear;
  813.          field_info.clear;
  814.          method_info.clear;
  815.       end;
  816.  
  817.    put_magic is
  818.          -- CAFEBABE ;-)
  819.       do
  820.          b_put_byte_string("%/202/%/254/%/186/%/190/");
  821.       end;
  822.  
  823.    put_minor_version is
  824.       do
  825.          b_put_u2(3);
  826.       end;
  827.  
  828.    put_major_version is
  829.       do
  830.          b_put_byte_string("%/0/%/45/");
  831.       end;
  832.  
  833.    args_field is
  834.          -- Define `args' field to store command line arguments.
  835.       local
  836.          args_idx, jaos_idx: INTEGER;
  837.          cp: like constant_pool;
  838.       do
  839.          cp := constant_pool;
  840.          args_idx := cp.idx_utf8(fz_74);
  841.          jaos_idx := cp.idx_utf8(fz_75);
  842.          field_info.add(9,args_idx,jaos_idx);
  843.       end;
  844.  
  845.    args_field_idx: INTEGER is
  846.       local
  847.          cp: like constant_pool;
  848.       do
  849.          cp := constant_pool;
  850.          Result := cp.idx_fieldref3(jvm_root_class,fz_74,fz_75);
  851.       end;
  852.  
  853.    out_file: BINARY_FILE_WRITE is
  854.          -- Current output class file.
  855.       once
  856.          !!Result.make;
  857.       end;
  858.  
  859.    out_file_path: STRING is
  860.       once
  861.          !!Result.make(32);
  862.       end;
  863.  
  864.    tmp_string: STRING is
  865.       once
  866.          !!Result.make(16);
  867.       end;
  868.  
  869.    push_direct(cpc: CALL_PROC_CALL) is
  870.       require
  871.          cpc /= Void
  872.       do
  873.          stack_push(C_direct_call);
  874.          stack_cpc.put(cpc,top);
  875.          direct_call_count := direct_call_count + 1;
  876.       end;
  877.  
  878.    push_check(cpc: CALL_PROC_CALL) is
  879.       require
  880.          cpc /= Void
  881.       do
  882.          stack_push(C_check_id);
  883.          stack_cpc.put(cpc,top);
  884.       end;
  885.  
  886.    opcode_check_id_for(e: EXPRESSION) is
  887.          -- Produce byte-code for `e' with non-void check and id
  888.          -- check.
  889.          -- Finally, also add a `checkcast' opcode.
  890.       require
  891.          e.result_type.run_class.running.count = 1
  892.       local
  893.          point1, point2: INTEGER;
  894.          rc: RUN_CLASS;
  895.          ct: TYPE;
  896.          ca: like code_attribute;
  897.       do
  898.          e.compile_to_jvm;
  899.          rc := e.result_type.run_class.running.first;
  900.          ct := rc.current_type;
  901.          if run_control.no_check then
  902.             ca := code_attribute;
  903.             ca.opcode_dup;
  904.             point1 := ca.opcode_ifnull;
  905.             ca.opcode_dup;
  906.             rc.opcode_instanceof;
  907.             point2 := ca.opcode_ifne;
  908.             ca.resolve_u2_branch(point1);
  909.             ca.opcode_dup;
  910.             ca.runtime_error_bad_target(e.start_position,ct,Void);
  911.             ca.resolve_u2_branch(point2);
  912.             rc.jvm_check_class_invariant;
  913.          end;
  914.          rc.opcode_checkcast;
  915.       end;
  916.  
  917.    bfw_connect(bfw: BINARY_FILE_WRITE; path: STRING) is
  918.       require
  919.          not bfw.is_connected;
  920.          path /= Void
  921.       do
  922.          bfw.connect_to(path);
  923.          if bfw.is_connected then
  924.             echo.put_string("Writing %"");
  925.             echo.put_string(path);
  926.             echo.put_string("%" file.%N");
  927.          else
  928.             echo.w_put_string("Cannot write file %"");
  929.             echo.w_put_string(path);
  930.             echo.w_put_string(fz_b0);
  931.             die_with_code(exit_failure_code);
  932.          end;
  933.       ensure
  934.          bfw.is_connected
  935.       end;
  936.  
  937. end -- JVM
  938.  
  939.